package taishan

import (
	"gitee.com/tiger000/taishan_web/taishan/pathArray"
	"github.com/rs/zerolog/log"
	"sync"
)

// Routers 路由组
// 按照host存储多个路由，方便后期根据host进行更新
type Routers struct {
	routers sync.Map
}

// Get 获取路由规则
func (that *Routers) Get(host string) *Router {
	//host 路由
	value, ok := that.routers.Load(host)
	if ok {
		route := value.(*Router)
		return route
	}
	return nil
}
func (that *Routers) GetHandlers(host, method, urlPath string) (handlers []HandlerFunc, matchedNode *Node) {
	//host 路由
	var nodes []*Node
	value, ok := that.routers.Load(host)
	if ok {
		route := value.(*Router)
		nodes = route.getRouteNodes(urlPath)
	}
	//全局路由
	var rootNodes []*Node
	value, ok = that.routers.Load(defaultHost)
	if ok {
		route := value.(*Router)
		rootNodes = route.getRouteNodes(urlPath)
	}

	//移除相同的node
	for _, node := range nodes {
		for key, rootNode := range rootNodes {
			if node.pattern == rootNode.pattern {
				rootNodes = append(rootNodes[:key], rootNodes[key+1:]...)
			}
		}
	}

	for key, node := range rootNodes {
		for _, middleware := range node.middlewares {
			handlers = append(handlers, middleware.HandlerFunc)
			log.Debug().Str("trace_id", method+" "+host+urlPath+" default").Str("middleware:", middleware.Name()).Msg("")
		}

		if key == len(rootNodes)-1 {
			matchedNode = rootNodes[len(rootNodes)-1]
			handler := matchedNode.getMethodHandler(method)
			if handler != nil {
				log.Debug().Str("trace_id", method+" "+host+urlPath+" default").Str("route", matchedNode.pattern).Msg("")
				handlers = append(handlers, handler)
			}

		}

	}
	for key, node := range nodes {
		for _, middleware := range node.middlewares {
			handlers = append(handlers, middleware.HandlerFunc)
			log.Debug().
				Str("trace_id", method+" "+host+urlPath).
				Str("middleware:", middleware.Name()).Msg("")
		}

		if key == len(nodes)-1 {
			matchedNode = nodes[len(nodes)-1]
			handler := matchedNode.getMethodHandler(method)
			if handler != nil {
				log.Debug().
					Str("trace_id", method+" "+host+urlPath).
					Str("route", matchedNode.pattern).Msg("")
				handlers = append(handlers, handler)
			}

		}

	}
	if matchedNode == nil {
		log.Error().Str("trace_id", method+" "+host+urlPath).Msg("未找到对应路由")
	}
	return
}

// Set 存储路由规则
func (that *Routers) Set(host string, route *Router) {
	that.routers.Store(host, route)
}

// Router 路由
// 按照method存储路由信息
// all method 使用all关键字，避免同时注册多个
// roots key eg, roots['GET'] roots['POST']
// handlers key eg, handlers['GET-/p/:lang/doc'], handlers['POST-/p/book']
type Router struct {
	//roots map[string]*Node //存储method->routeNode对应信息
	//handlers map[string]HandlerFunc
	rootRouter *Node
}

func newRouter() *Router {
	return &Router{
		rootRouter: &Node{pattern: "/"},
	}
}

// 设置方法路由
func (r *Router) setRoute(method string, route string, handler HandlerFunc) error {
	return r.rootRouter.insertRoute(method, route, handler)
}

// 获取方法路由节点
func (r *Router) getRouteNode(urlPath string) *Node {
	searchParts, _ := pathArray.Parse(urlPath)
	//搜索带域名的路由
	return r.rootRouter.search(searchParts, 1)

}

// 获取方法路由对应的方法
func (r *Router) getRouteHandler(method string, urlPath string) HandlerFunc {
	routeNode := r.getRouteNode(urlPath)
	return routeNode.getMethodHandler(method)
}

// UpdateRoutes 暂时不要使用该方法
func (r *Router) updateRoute(method string, routeRule string, handler HandlerFunc) error {
	return r.rootRouter.updateRoute(method, routeRule, handler)
}

// 设置中间件
func (r *Router) setMiddlewares(route string, middlewares ...IMiddleware) error {
	return r.rootRouter.insertMiddlewares(route, middlewares...)
}

// 设置中间件
func (r *Router) updateMiddlewares(route string, middlewares ...IMiddleware) error {
	return r.rootRouter.updateMiddlewares(route, middlewares...)
}

// 获取所有匹配的路由节点, 以优先级由低到高排列
func (r *Router) getRouteNodes(urlPath string) (res []*Node) {
	searchParts, _ := pathArray.Parse(urlPath)
	//搜索带域名的路由
	r.rootRouter.searchAllNodes(searchParts, 1, &res)
	return
}
func (r *Router) Print() {
	r.rootRouter.Print(0)
}
